<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Auth0 React</title>
  </head>
  <body>
    <div id="app"></div>
    <link rel="stylesheet" href="https://unpkg.com/water.css@2/out/water.css" />
    <style>body { max-width: 1440px } label { width: 33% } input { width: 85% } label:has(input[type="checkbox"]) {width: 20%}</style>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script src="https://unpkg.com/babel-polyfill@6/dist/polyfill.min.js"></script>
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="auth0-react.js"></script>
    <script type="text/babel" data-presets="es2015,es2016,es2017,stage-3,react">
      const { Auth0Provider, useAuth0 } = reactAuth0;
      const { useState, useEffect } = React;

      const defaultConfig = {
        domain: 'brucke.auth0.com',
        clientId: 'wLSIP47wM39wKdDmOj6Zb5eSEw3JVhVp',
        audience: 'default',
        scope: 'openid profile email',
        useMrrt: false,
        useDpop: false,
        useRefreshTokens: false,
        connection: '',
        connectScope: ''
      };

      function useLocalStorage(key, initialValue) {
        const [storedValue, setStoredValue] = useState(() => {
          const item = window.localStorage.getItem(key);
          return item ? JSON.parse(item) : initialValue;
        });
        useEffect(() => {
          window.localStorage.setItem(key, JSON.stringify(storedValue));
        }, [key, storedValue]);
        return [storedValue, setStoredValue];
      }

      function ConfigForm({ config, handleChange }) {
        return (
          <form style={{ marginBottom: 20 }}>
            <label>
              Domain
              <input name="domain" value={config.domain} onChange={handleChange} placeholder="Domain" />
            </label>
            <label>
              Client ID
              <input name="clientId" value={config.clientId} onChange={handleChange} placeholder="Client ID" />
            </label>
            <label>
              Audience
              <input name="audience" value={config.audience} onChange={handleChange} placeholder="Audience" />
            </label>
            <label>
              Scope
              <input name="scope" value={config.scope} onChange={handleChange} placeholder="Scope" />
            </label>
            <label>
              <input type="checkbox" name="useRefreshTokens" checked={config.useRefreshTokens} onChange={handleChange} />
              useRefreshTokens
            </label>
            <label>
              <input type="checkbox" name="useMrrt" checked={config.useMrrt} onChange={handleChange} />
              useMrrt
            </label>
            <label>
              <input type="checkbox" name="useDpop" checked={config.useDpop} onChange={handleChange} />
              useDpop
            </label>
          </form>
        );
      }

      const Playground = ({ config, setConfig, data, setData, handleChange }) => {
        const {
          user,
          error,
          isAuthenticated,
          isLoading,
          getIdTokenClaims,
          getAccessTokenSilently,
          getAccessTokenWithPopup,
          loginWithRedirect,
          loginWithPopup,
          connectAccountWithRedirect,
          logout,
        } = useAuth0();
        const [token, setToken] = useState(null);

        const changeToAuth0 = () => {
          setConfig(defaultConfig);
        };

        function changeToNodeOidc() {
          setConfig({
            ...defaultConfig,
            domain: 'http://127.0.0.1:3000',
            clientId: 'testing',
            useDpop: true,
          });
        }

        useEffect(() => {
          error && setData(error);
        }, [error]);

        if (isLoading) {
          return <div>loading...</div>;
        }

        return isAuthenticated ? (
          <div>
            <h3 id="hello">Hello, {user.name}!</h3>
            <button
              id="logout"
              onClick={() => logout({ returnTo: window.location.origin })}
            >
              logout
            </button>
            <button
              onClick={async () => setToken(await getAccessTokenSilently())}
            >
              Get access token
            </button>
            <button
              onClick={async () => setToken(await getAccessTokenWithPopup())}
            >
              Get token with popup
            </button>
            <button onClick={async () => setData(await getIdTokenClaims())}>
              Get id_token claims
            </button>
            <fieldset>
              <label>
                Connection
                <input name="connection" value={config.connection} onChange={handleChange} placeholder="Connection" />
              </label>
              <label>
                Scope
                <input name="connectScope" value={config.connectScope} onChange={handleChange} placeholder="Connect Scope" />
              </label>
              <button
                onClick={async () => await connectAccountWithRedirect({ connection: config.connection, scope: config.connectScope }).catch(e => setData(e))}
                disabled={!config.connection || !config.connectScope}
              >
                Connect Account
              </button>
            </fieldset>
            {token && <pre>access_token: {token}</pre>}
            {data && (
              <pre>data: {JSON.stringify(data, null, 2)}</pre>
            )}
          </div>
        ) : (
          <div>
            <button id="login" onClick={() => loginWithRedirect({ authorizationParams: { scope: config.scope }})}>
              Login with redirect
            </button>
            <button onClick={() => loginWithPopup({ authorizationParams: { scope: config.scope }})}>Login with popup</button>

            <button data-cy="use-auth0" onClick={() => changeToAuth0()}>
              Use Auth0
            </button>
            <button
              data-cy="use-node-oidc-provider"
              onClick={() => changeToNodeOidc()}
            >
              Use Node OIDC Provider
            </button>
            {data && (
              <pre>data: {JSON.stringify(data, null, 2)}</pre>
            )}
          </div>
        );
      };

      const App = () => {
        const [config, setConfig] = useLocalStorage('auth0-react-playground', defaultConfig);
        const [data, setData] = useState(null);

        function handleChange(e) {
          const { name, value, type, checked } = e.target;
          setConfig(prev => ({
            ...prev,
            [name]: type === 'checkbox' ? checked : value
          }));
        }

        return (
          <React.StrictMode>
            <h1>Auth0 React</h1>
            <ConfigForm config={config} handleChange={handleChange} />
            <Auth0Provider
              domain={config.domain}
              clientId={config.clientId}
              key={JSON.stringify(config)}
              authorizationParams={{
                redirect_uri: window.location.origin,
                audience: config.audience || 'default'
              }}
              useRefreshTokens={config.useRefreshTokens}
              useMrrt={config.useMrrt}
              useDpop={config.useDpop}
              cacheLocation="localstorage"
              onRedirectCallback={appState => {
                if (appState.connectedAccount) setData(appState.connectedAccount);
                window.history.replaceState({}, document.title, '/');
              }}
            >
              <Playground config={config} setConfig={setConfig} data={data} setData={setData} handleChange={handleChange} />
            </Auth0Provider>
          </React.StrictMode>
        );
      };

      const root = ReactDOM.createRoot(document.getElementById('app'));
      root.render(<App />);
    </script>
  </body>
</html>
